import { reactive, ref, onUnmounted } from '@vue/composition-api'
type PTime = number | string
interface IResult {
  days: PTime
  hours: PTime
  minutes: PTime
  seconds: PTime
  text: string
}
type PFn = () => void

interface ICountDownConfig {
  firstDate: number // 时间戳
  firstText?: string // 文本
  firstEndFn?: PFn // 第一个倒计时结束回调的函数
  secondDate?: number // 时间戳
  secondText?: string // 文本
  secondEndFn?: PFn // 第二个倒计时结束回调的函数
  showDays?: boolean // 是否显示天
  endFn?: PFn // 进入就结束
}
enum DownPending {
  noPending,
  firstPending,
  secondPending,
}

// 小程序slot 插槽取不到当前页面的变量 修改成hook
export function useCountDown(config: ICountDownConfig) {
  const result = reactive<IResult>({ days: 0, hours: 0, minutes: 0, seconds: 0, text: '' })
  let downPending = DownPending.noPending

  const dateDiff = (firstDate: number, secondDate: number | undefined) => {
    const currentTime = new Date().getTime()
    const firstTime = firstDate
    const secondTime = secondDate || 0
    let diffTime = 0
    if (currentTime < firstTime - 1000) {
      diffTime = firstTime - currentTime
      result.text = config.firstText || ''
      downPending = DownPending.firstPending
    } else if (currentTime >= firstTime - 1000 && currentTime < secondTime) {
      diffTime = secondTime - currentTime
      result.text = config.secondText || ''
      downPending = DownPending.secondPending
    } else {
      diffTime = 0
      downPending = DownPending.noPending
      config.endFn && config.endFn()
    }
    return diffTime
  }

  const getTime = () => {
    let diffTime = 0
    diffTime = dateDiff(config.firstDate, config.secondDate)
    return Math.floor(diffTime / 1000)
  }
  let timestamp = getTime()

  let timer = 0
  const seconds = ref(0)
  // 清除定时器
  const clearTimer = () => {
    if (timer) {
      clearInterval(timer)
      timer = 0
    }
  }
  // 停止倒计时
  const end = () => {
    clearTimer()
    if (downPending === 2 && config.secondEndFn) {
      config.secondEndFn()
    }
    if (downPending === 1) {
      if (config.firstEndFn) {
        config.firstEndFn()
      }
      if (config.secondDate) {
        timestamp = getTime()
        start()
      }
    }
  }
  // 格式化时间
  const formatTime = (seconds: number) => {
    // 小于等于0的话，结束倒计时
    seconds <= 0 && end()
    let day: PTime = 0
    let hour: PTime = 0
    let minute: PTime = 0
    let second: PTime = 0
    day = Math.floor(seconds / (60 * 60 * 24))
    // 判断是否显示“天”参数，如果不显示，将天部分的值，加入到小时中
    // hour为给后面计算秒和分等用的(基于显示天的前提下计算)
    hour = Math.floor(seconds / (60 * 60)) - day * 24
    // showHour为需要显示的小时
    let showHour: PTime
    if (config.showDays) {
      showHour = hour
    } else {
      // 如果不显示天数，将“天”部分的时间折算到小时中去
      showHour = Math.floor(seconds / (60 * 60))
    }
    minute = Math.floor(seconds / 60) - hour * 60 - day * 24 * 60
    second = Math.floor(seconds) - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60
    // 如果小于10，在前面补上一个"0"
    showHour = showHour < 10 ? '0' + showHour : showHour
    minute = minute < 10 ? '0' + minute : minute
    second = second < 10 ? '0' + second : second
    day = day < 10 ? '0' + day : day
    result.days = day
    result.hours = showHour
    result.minutes = minute
    result.seconds = second
  }
  // 倒计时
  const start = () => {
    // 避免可能出现的倒计时重叠情况
    clearTimer()
    if (timestamp <= 0) return
    seconds.value = Number(timestamp)
    formatTime(seconds.value)
    timer = setInterval(() => {
      seconds.value--
      if (seconds.value < 0) {
        return end()
      }
      formatTime(seconds.value)
    }, 1000)
  }
  // 会报错
  onUnmounted(() => {
    clearInterval(timer)
    timer = 0
  })

  // 如果自动倒计时
  timestamp && start()

  return result
}
